Эта ошибка возникает, когда HTML, сгенерированный на сервере (SSR), не совпадает с HTML, который рендерится на клиенте. React ожидает, что серверный и клиентский HTML будут идентичны, чтобы успешно выполнить процесс «гидратации». Если они различаются, React сбрасывает серверный HTML и перерендеривает дерево на клиенте, что может повлиять на производительность.
Основные причины ошибки
- Использование
typeof window !== 'undefined'
или других клиентских проверок в SSR-компонентах.- Сервер не имеет доступа к объекту
window
, поэтому условные проверки, зависящие от клиента, могут привести к различиям в HTML.
- Сервер не имеет доступа к объекту
- Использование переменных, которые меняются при каждом рендере:
Date.now()
,Math.random()
или другие динамические значения, которые генерируют разные результаты на сервере и клиенте.
- Форматирование даты или локализация:
- Если сервер и клиент используют разные локали, это может привести к различиям в форматировании текста.
- Динамические данные без передачи их снимка (snapshot):
- Если данные, используемые для рендеринга, изменяются между сервером и клиентом, это вызовет несоответствие.
- Неправильная вложенность HTML-тегов:
- Например, использование некорректной структуры HTML, такой как
<div><p></div></p>
.
- Например, использование некорректной структуры HTML, такой как
- Браузерные расширения:
- Некоторые расширения могут изменять HTML до того, как React загрузится, что вызовет ошибку.
Как исправить ошибку
1. Проверка на typeof window
Если вы используете условие if (typeof window !== 'undefined')
, убедитесь, что оно применяется только в клиентских компонентах. Например:
javascript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | "use client"; import { useEffect, useState } from "react"; export default function Example() { const [isClient, setIsClient] = useState(false); useEffect(() => { setIsClient(true); }, []); return ( <div> {isClient ? <p>Это клиент</p> : <p>Загрузка...</p>} </div> ); } |
2. Избегайте использования Date.now()
и Math.random()
Если вам нужно использовать динамические значения, убедитесь, что они одинаковы на сервере и клиенте. Например:
javascript
1 | const randomValue = useMemo(() => 42, []); // Используйте фиксированное значение |
Или передавайте данные через props
:
javascript
1 2 3 4 5 6 7 8 9 10 11 | export async function getServerSideProps() { return { props: { timestamp: Date.now(), }, }; } export default function Page({ timestamp }) { return <p>Время: {timestamp}</p>; } |
3. Используйте одинаковую локаль
Если вы форматируете даты или числа, убедитесь, что сервер и клиент используют одну и ту же локаль. Например:
javascript
1 2 3 4 5 6 7 8 9 10 11 12 | import { useEffect, useState } from "react"; export default function Page() { const [formattedDate, setFormattedDate] = useState(""); useEffect(() => { const date = new Date(); setFormattedDate(date.toLocaleDateString("ru-RU")); }, []); return <p>Дата: {formattedDate || "Загрузка..."}</p>; } |
4. Передавайте данные через props
Если вы используете данные из API, убедитесь, что они передаются как props
на сервере:
javascript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | export async function getServerSideProps() { const res = await fetch("https://api.example.com/data"); const data = await res.json(); return { props: { data, }, }; } export default function Page({ data }) { return ( <div> {data.map((item) => ( <p key={item.id}>{item.name}</p> ))} </div> ); } |
5. Проверка HTML-структуры
Убедитесь, что HTML-теги правильно вложены. Например:Неправильно:
html
1 2 | <div> <p></div></p> |
Правильно:
html
1 2 3 | <div> <p></p> </div> |
6. Отключение SSR для компонента
Если компонент должен рендериться только на клиенте, используйте директиву "use client"
:
javascript
1 2 3 4 5 | "use client"; export default function ClientOnlyComponent() { return <p>Этот компонент рендерится только на клиенте</p>; } |
Дополнительные советы
- Проверяйте консоль браузера: Часто React указывает, какой компонент вызвал ошибку.
- Отключите расширения браузера: Попробуйте открыть сайт в режиме инкогнито, чтобы исключить влияние расширений.
- Используйте
React.StrictMode
: Это поможет выявить потенциальные проблемы в вашем коде.
Если ошибка сохраняется, напишите, и я помогу вам разобраться! 😊